﻿namespace ChinaUnicom
{
    using System;
    using System.Windows;
    using ChinaUnicom.Controls;
    using ChinaUnicom.Models;
    using ChinaUnicom.Net;
    using ChinaUnicom.Tasks;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Shell;
    using ChinaUnicom.Schedule;

    public partial class MainPage : PhoneApplicationPage
    {
        ItemCollection clientItemsModel = new ItemCollection();

        ItemCollection feeItemsModel = new ItemCollection();

        IScheduleQuene taskQueue;

        Progressing progressing;

        bool isFeeInfoInitialized = false;

        bool isInitialized = false;

        Context Context { get { return (Application.Current as App).Context; } }

        // Constructor
        public MainPage()
        {
            taskQueue = new SerialQuene();
            taskQueue.Error += OnTaskQueueError;

            InitializeComponent();

            progressing = new Progressing(progressBar);

            feeDetailsinfo.ItemsSource = feeItemsModel;
            clientInfo.ItemsSource = clientItemsModel;
        }

        #region Tasks

        AutoLoginTask AutoLoginTask
        {
            get
            {
                AutoLoginTask.Task.Failed -= OnAutoLoginFailed;
                AutoLoginTask.Task.Completed -= OnSigned;
                AutoLoginTask.Task.Failed += OnAutoLoginFailed;
                AutoLoginTask.Task.Completed += OnSigned;
                return AutoLoginTask.Task;
            }
        }

        PackageTask pTask;
        PackageTask PackageTask
        {
            get
            {
                if (pTask == null)
                {
                    pTask = new PackageTask();
                    pTask.Completed += OnPackageLoadCompleted;
                    pTask.Started += ShowProgressing;
                }
                return pTask;
            }
        }

        FeeTask fTask;
        FeeTask FeeTask
        {
            get
            {
                if (fTask == null)
                {
                    fTask = new FeeTask();
                    fTask.Completed += OnFeeLoadCompleted;
                    fTask.Started += ShowProgressing;
                }
                return fTask;
            }
        }

        ClientTask cTask;
        ClientTask ClientTask
        {
            get
            {
                if (cTask == null)
                {
                    cTask = new ClientTask();
                    cTask.Completed += OnClientLoadCompleted;
                    cTask.Started += ShowProgressing;

                } return cTask;
            }
        }

        #endregion

        #region on navigation

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            if (isInitialized)
            {
                return;
            }
            // the ui workflow
            Authentication auth = Authentication.Current;
            bool isNetworkAvailable = NetworkChecking();

            if (auth.Authorized && isNetworkAvailable)
            {
                isInitialized = true;
                // 1. authentication and network is OK.
                UpdateFromLocal();
                UpdateFromRemoting();
            }
            else if (auth.Authorized)
            {
                // 2. authentication is OK, but network.
                UpdateFromLocal();
            }
            else if (isNetworkAvailable)
            {
                // 3. no authentication, but network is OK.
                NavigationService.Navigate(new Uri("/Settings.xaml?login=yes", UriKind.Relative));
            }
            else
            {
                // 4. neither.
                MessageBox.Show("无法连接网络！", "温馨提示", MessageBoxButton.OK);
            }

            if (!string.IsNullOrEmpty(Context.Account.ClientName) && clientLabel.Visibility == System.Windows.Visibility.Collapsed)
            {
                clientLabelName.Text = Context.Account.ClientName;
                clientLabelMobile.Text = Context.Account.Mobile;
                clientLabel.Visibility = System.Windows.Visibility.Visible;
            }

            if (Authentication.Current.Signed)
            {
                (ApplicationBar.Buttons[0] as ApplicationBarIconButton).IsEnabled = true;
            }

            base.OnNavigatedTo(e);
        }

        void UpdateFromLocal()
        {
            UpdatePackageInfo(Context.Package);
            UpdateFeeInfo(Context.Fee);
            UpdateClientInfo(Context.Client);
        }

        void UpdateFromRemoting()
        {
            // before

            // first time.
            if (Authentication.Current.Signed)
            {
                taskQueue.Schedule(PackageTask);
                taskQueue.Schedule(FeeTask);
                taskQueue.Schedule(ClientTask);
            }
            else if (Authentication.Current.Authorized)
            {
                taskQueue.Schedule(AutoLoginTask);
                taskQueue.Schedule(PackageTask);
            }
        }

        void OnSigned(object sender, EventArgs e)
        {
            this.Dispatcher.BeginInvoke(() => { (ApplicationBar.Buttons[0] as ApplicationBarIconButton).IsEnabled = true; });

            AutoLoginTask.Task.Failed -= OnAutoLoginFailed;
            AutoLoginTask.Task.Completed -= OnSigned;
        }

        void OnAutoLoginFailed(object sender, EventArgs e)
        {
            AutoLoginTask task = sender as AutoLoginTask;
            this.Dispatcher.BeginInvoke(() => MessageBox.Show(task.Message, "温馨提示", MessageBoxButton.OK));

            AutoLoginTask.Task.Failed -= OnAutoLoginFailed;
            AutoLoginTask.Task.Completed -= OnSigned;
        }

        void OnPackageLoadCompleted(object sender, EventArgs e)
        {
            PackageTask task = sender as PackageTask;
            this.Dispatcher.BeginInvoke(() =>
            {
                progressing.Hide();
                Context.Package = task.Package;
                UpdatePackageInfo(task.Package);
            });
        }

        void OnFeeLoadCompleted(object sender, EventArgs e)
        {
            FeeTask task = sender as FeeTask;
            this.Dispatcher.BeginInvoke(() =>
            {
                progressing.Hide();
                Context.Fee = task.Fee;
                UpdateFeeInfo(task.Fee);
            });
        }

        void OnClientLoadCompleted(object sender, EventArgs e)
        {
            ClientTask task = sender as ClientTask;
            this.Dispatcher.BeginInvoke(() =>
            {
                progressing.Hide();
                Context.Client = task.Client;
                UpdateClientInfo(task.Client);

                if (!string.IsNullOrEmpty(Context.Account.ClientName) && clientLabel.Visibility == System.Windows.Visibility.Collapsed)
                {
                    clientLabelName.Text = Context.Account.ClientName;
                    clientLabelMobile.Text = Context.Account.Mobile;
                    clientLabel.Visibility = System.Windows.Visibility.Visible;
                }
            });
        }

        void OnTaskQueueError(object sender, ScheduleExceptionArgs e)
        {
            this.Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show(e.Exception.Message, "温馨提示", MessageBoxButton.OK);
            });
        }

        #endregion

        #region members

        void ShowProgressing(object sender, EventArgs e)
        {
            this.Dispatcher.BeginInvoke(() => progressing.Show());
        }

        void UpdatePackageInfo(Package package)
        {
            // TODO: need to update.
            packageBaseinfo.DataContext = package;
            packageBaseinfo.Visibility = System.Windows.Visibility.Visible;
            packageList.Items = package.Items;
        }

        void UpdateFeeInfo(Fee fee)
        {
            // TODO: need to update.
            feeBaseinfo.DataContext = fee;
            feeBaseinfo.Visibility = System.Windows.Visibility.Visible;
            feeDetailsinfo.ItemsSource = fee.Items;
        }

        void UpdateClientInfo(Client client)
        {
            // TODO: need to update.
            clientInfo.ItemsSource = client.Items;
        }

        #endregion

        #region events

        private void OnMainContainerSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (isFeeInfoInitialized) return;

            var pivot = sender as Pivot;
            if (pivot.SelectedIndex == 1)
            {
                taskQueue.Schedule(FeeTask);
                isFeeInfoInitialized = true;
            }
        }

        private void OnRefreshClick(object sender, EventArgs e)
        {
            switch (mainContainer.SelectedIndex)
            {
                case 0:
                    // 套餐余量
                    taskQueue.Schedule(PackageTask);
                    break;
                case 1:
                    // 当月话费
                    taskQueue.Schedule(FeeTask);
                    break;
                case 2:
                    // 我的信息
                    taskQueue.Schedule(ClientTask);
                    break;
            }
        }

        private void OnSettingsPageClick(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative));
        }

        #endregion

        #region network

        private bool NetworkChecking()
        {
            var network = Helper.Network;
            if (!network.IsNetworkAvailable)
            {
                network.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;
            }

            return network.IsNetworkAvailable;
        }

        void OnNetworkAvailabilityChanged(object sender, NotificationEventArgs e)
        {
            // TODO: network is availabled.

            // do something...
            // e.Type == NotificationType.Availabled
            // e.Type == NotificationType.Unavailabled
        }

        #endregion
    }
}
